// SPDX-License-Identifier: GPL-2.0
/*
 * RECLAIM: RECLAIM AN SHARED MEMORY
 *
 * (C) 2024.05.01 BuddyZhang1 <buddy.zhang@aliyun.com>
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <malloc.h>
#include <sys/ioctl.h>
#include <sys/mman.h>

#define DEV_PATH		"/dev/BiscuitOS-RECLAIM"
#define errExit(msg)		do { perror(msg); exit(EXIT_FAILURE); } \
				     while (0)
#define BISCUITOS_IO		0xBD
#define BS_RECLAIM		_IO(BISCUITOS_IO, 0x00)
#define BS_RECLAIM_PREPARE	_IO(BISCUITOS_IO, 0x01)
#define MAP_VADDR		0x6000000000
#define MAP_SIZE		0x1000

int main()
{
	void *base;
	int fd;

	/* OPEN SPECIAL FILE */
	fd  = open(DEV_PATH, O_RDWR);
	if (fd < 0)
		errExit("Open FILE failed");

	/* ALLOC SHARED MEMORY */
	base = mmap((void *)MAP_VADDR, MAP_SIZE,
		    PROT_READ | PROT_WRITE,
		    MAP_ANONYMOUS | MAP_SHARED,
		    -1,
		    0);
	if (base == MAP_FAILED)
		errExit("MMAP Failed");

	/* ACCESS, TRIGGER #PF */
	*(char *)base = 'B';

	/* MARK PAGE LATEST UNUSED */
	ioctl(fd, BS_RECLAIM_PREPARE, (unsigned long)base);

	/* RECLAIM */
	ioctl(fd, BS_RECLAIM, (unsigned long)base);

	/* REUSER */
	*(char *)base = 'C';

	/* FREE RESOURCE */
	munmap(base, MAP_SIZE);
	close(fd);

	return 0;
}
